package jj.rmirm.gui;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;

import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JToolBar;

import jj.rmirm.interfaces.LogDisplayObservable;
import jj.rmirm.interfaces.LogDisplayObserver;
import jj.rmirm.manager.MonitorThread;

public class ToolBar extends JToolBar implements LogDisplayObservable{

	public ToolBar(JTextArea monitorLog, ObjListDisplay objListDisplay) {
		super("RMI Registry Monitor Toolbar");
		this.setFloatable(false);
		
		this.ButtonEventListeners = new Listeners();
		this.addComponents();
		
		//adding observer
		this.logDisplay = new LogDisplay(monitorLog);
		this.informObservers(WELCOME);
		
		this.objListDisplay = objListDisplay;
	}
	
	@Override
	public void registerObserver(LogDisplayObserver ldo) {
		
	}
	
	@Override
	public void informObservers(String message) {
		this.logDisplay.display(message);
	}
	
	/**
	 * Use this method to validate ip address from combobox
	 * @return - choosen server ip address or -1 if error
	 */
	public String getIp() {
		
		String ip = (String)this.ipAddrBox.getSelectedItem();

		if(ip.contains(".")) {
			String [] parts = ip.split ("\\.");
	        for (String s : parts) {
	        	try {
	        		int i = Integer.parseInt(s);
		            if (i < 0 || i > 254) {
		                ip = "-1";
		                break;
		            }
	        	} catch (Exception e) {
	        		ip = "-1";
	        	}
	        }//for
		}//if(ip.contains(".")
		
		return ip;
	}
	
	/**
	 * Use this method to get validated port from textfield
	 * @return - choosen server port number for RMI Registry or -1 if not a port
	 */
	public int getPort() {
		int port;
		try {
			port = Integer.parseInt(this.portBox.getText());
			
			if(port < 1 || port > 655535)
				port = -1;
		} catch (Exception e) {
			port = -1;
		}
		
		return port;
	}
	
	/**
	 *  adds visual components to tool bar
	 */
	protected void addComponents() {
		
		//ip address box
		this.ipAddrBox = new JComboBox();
		this.ipAddrBox.addItem("127.0.0.1");
		this.ipAddrBox.setEditable(true);
		this.ipAddrBox.setToolTipText("Server ip address");
		
		
		//port field
		this.portBox = new JTextField("1099");
		this.portBox.setColumns(5);
		this.portBox.setToolTipText("Server port");

		//monitor button
		this.monitorButton = this.createButton("monitor", 
											    MONITOR, 
											    "Monitor choosen server", 
											    "M");
		
		//start button
		this.startButton = this.createButton("start", 
											  START,
											  "Start local registry",
											  ">");
		
		//stop button
		this.stopButton = this.createButton("stop", 
				  							STOP,
				  							"Stop local registry / monitoring",
				  							"x");
		
		//restart button
		this.restartButton = this.createButton("restart", 
				  								RESTART,
				  								"Restart registry",
				  								"R");
		this.restartButton.setEnabled(false);
		
		//clean button
		//stops the registry and tries to run garbage collector
		this.cleanButton = this.createButton("clean", 
				  							  CLEAN,
				  							  "Stop & clean",
				  							  "c");
		this.cleanButton.setEnabled(false);
		
		JPanel toolBarPanel = new JPanel();
		toolBarPanel.setLayout(new BoxLayout(toolBarPanel, BoxLayout.X_AXIS));
		toolBarPanel.add(ipAddrBox);
		toolBarPanel.add(portBox);
		toolBarPanel.add(monitorButton);
		toolBarPanel.add(startButton);
		toolBarPanel.add(stopButton);
		toolBarPanel.add(restartButton);
		toolBarPanel.add(cleanButton);
		
		this.setLayout(new BorderLayout());
		this.add(toolBarPanel, BorderLayout.WEST);
		this.add(new JPanel(), BorderLayout.CENTER);

	}
	
	protected JButton createButton (String imageName,
									String actionCommand,
									String toolTipText,
									String altText) {
		//Look for the image.
	    String imgLocation = "/resources/"
	                         + imageName
	                         + ".gif";
	    URL imageURL = ToolBar.class.getResource(imgLocation);


	    //Create and initialize the button.
	    JButton button = new JButton();
	    button.setActionCommand(actionCommand);
	    button.setToolTipText(toolTipText);
	    button.addActionListener(this.ButtonEventListeners);

	    if (imageURL != null) {                      //image found
	        button.setIcon(new ImageIcon(imageURL, altText));
	    } else {                                     //no image found
	        button.setText(altText);
	        this.informObservers(RESOURCE_NOT_FOUND + imgLocation);
	    }

	    return button;

	}
	
	private static final long serialVersionUID = -2816425290385683553L;
	
	static final String MONITOR = "monitor";
	static final String START = "start";
	static final String STOP = "stop";
	static final String RESTART = "restart";
	static final String CLEAN = "clean";
	
	private JComboBox ipAddrBox;
	private JTextField portBox;
	private JButton monitorButton;
	private JButton startButton;
	private JButton stopButton;
	private JButton restartButton;
	private JButton cleanButton;
	private Listeners ButtonEventListeners;
	
	private MonitorThread mt;
	private LogDisplay logDisplay;
	private ObjListDisplay objListDisplay;	
	
	public static final String WELCOME = "Ready";
	public static final String NO_SUCH_COMMAND = "No such command: ";
	public static final String RESOURCE_NOT_FOUND = "Resource not found: ";
	
	/**
	 * listener class for buttons
	 * @author jarek
	 *
	 */
	class Listeners implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			
			String cmd = e.getActionCommand();
			
			if(cmd.equals(MONITOR)){
				this.setButtonsEnable(false, false, true, false, true);
				this.setRmi(false);
				
			} else if(cmd.equals(START)) {
				this.setButtonsEnable(false, false, true, true, true);		
				this.setRmi(true);
				
			}else if(cmd.equals(STOP)) {
				this.setButtonsEnable(true, true, true, false, true);
				if(mt != null) {
					mt.setStop(true);
					//need to wait until previous registry will be done
					while(!mt.isDone()) {}
					objListDisplay.clear();
				}
				
			}else if(cmd.equals(RESTART)) {
				mt.setStop(true);
				//need to wait until previous registry will be done
				while(!mt.isDone()) {}
				
				this.setRmi(true);
				
			}else if(cmd.equals(CLEAN)) {
				stopButton.doClick();
				cleanButton.setEnabled(false);
				logDisplay.clear();
				informObservers(WELCOME);
				System.gc();
				
			}else
				informObservers(NO_SUCH_COMMAND + cmd);
		}
		
		private void setRmi(boolean startLocalRegistry) {
			mt = new MonitorThread(logDisplay, objListDisplay);
			mt.setServerParams(getIp(), getPort());
			mt.startLocalRegistry(startLocalRegistry);
			mt.execute();
		}
		
		private void setButtonsEnable(boolean btMonitor,
									  boolean btStart,
									  boolean btStop,
									  boolean btRestart,
									  boolean btClean) {

			monitorButton.setEnabled(btMonitor);
			startButton.setEnabled(btStart);
			stopButton.setEnabled(btStop);
			restartButton.setEnabled(btRestart);
			cleanButton.setEnabled(btClean);
		}
		
	}
}
